package com.example.javagobang.model;

import com.example.javagobang.JavaGobangApplication;
import com.example.javagobang.game.OnlineUser;
import com.example.javagobang.game.RoomManager;
import com.example.javagobang.mapper.UserInfoMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.swing.*;
import java.io.IOException;
import java.io.PipedReader;
import java.util.UUID;

public class Room {
    private String roomId;
    private UserInfo user1;
    private UserInfo user2;
    private int whiteUser;
    private static int MAX_ROW = 15;
    private static int MAX_COL = 15;

    private ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 注意从spring中拿到这里的对象，不能直接通过普通new对象
     */
    private OnlineUser onlineUser ;
    private RoomManager roomManager ;

    private UserInfoMapper userInfoMapper;

    private int[][] board = new int[MAX_ROW][MAX_COL];

    public void putChess(String reqJson) throws IOException {
        // 1. 记录当前落子的位置.
        GameRequest request = objectMapper.readValue(reqJson, GameRequest.class);
        GameResponse response = new GameResponse();

        int chess = request.getUserId() == user1.getUserId() ? 1 : 2;
        int row = request.getRow();
        int col = request.getCol();
        if (board[row][col] != 0) {
            // 在客户端已经针对重复落子进行过判定了. 此处为了程序更加稳健, 在服务器再判定一次.
            System.out.println("当前位置 (" + row + ", " + col + ") 已经有子了!");
            return;
        }

        board[row][col] = chess;

        //棋盘的打印
        printBoard();
        //判断胜负
        int winner = checkWinner(row, col, chess);

        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);

        // 要想给用户发送 websocket 数据, 就需要获取到这个用户的 WebSocketSession
        WebSocketSession session1 = onlineUser.getFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUser.getFromGameRoom(user2.getUserId());

        if(session1 == null){
            //说明玩家一已经下线了
            System.out.println("玩家2获胜");
            response.setWinner(user2.getUserId());
        }
        if(session2 == null){
            System.out.println("玩家1获胜");
            response.setWinner(user1.getUserId());
        }
        //数据信息的响应返回
        String respJson = objectMapper.writeValueAsString(response);

        if (session1 != null) {
            session1.sendMessage(new TextMessage(respJson));
        }
        if (session2 != null) {
            session2.sendMessage(new TextMessage(respJson));
        }

        //房间的删除
        if(response.getWinner() != 0){
            System.out.println("胜负已分，房间关闭");
            int userWin = response.getWinner();
            int userLose = (response.getWinner() == user1.getUserId())? user2.getUserId() : user1.getUserId();
            userInfoMapper.userWin(userWin);
            userInfoMapper.userLose(userLose);
            roomManager.remove(roomId,user1.getUserId(),user2.getUserId());
        }

    }

    private void printBoard() {

        System.out.println("当前对局情况");
        System.out.println("=======================");
        for (int i = 0 ;i < MAX_ROW ; i++){
            for (int j = 0; j < MAX_COL; j++) {
                System.out.print(board[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println("=======================");
    }
    //胜负判定的操作,
    private int checkWinner(int row, int col, int chess) {
        //横向判定操作
        for (int c = col - 4; c <= col; c++) {
            // 针对其中的一种情况, 来判定这五个子是不是连在一起了
            // 不光是这五个子得连着, 而且还得和玩家落的子是一样(才算是获胜)
            try {
                if (board[row][c] == chess
                        && board[row][c + 1] == chess
                        && board[row][c + 2] == chess
                        && board[row][c + 3] == chess
                        && board[row][c + 4] == chess) {
                    // 构成了五子连珠! 胜负已分!
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                // 如果出现数组下标越界的情况, 就在这里直接忽略这个异常.
                continue;
            }
        }

        //针对所有的列进行判断
        for(int r = row - 4;r <= row ; r++){
            try {
                if (board[r][col] == chess
                && board[r + 1][col] == chess
                && board[r + 2][col] == chess
                && board[r + 3][col] == chess
                && board[r + 4][col] == chess){
                    return chess == 1?user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }

        //针对所有左对角线
        for (int r = row - 4,c = col - 4;r <= row && c <= col ; r++,c++){
            try {
                if(board[r][c] == chess
                && board[r + 1][c + 1] == chess
                && board[r + 2][c + 2] == chess
                && board[r + 3][c + 3] == chess
                && board[r + 4][c + 4] == chess){
                    return chess == 1?user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }

        //针对右对角线
        for(int r = row - 4,c = col + 4;r <= row && c >= col;r++,c--){
            try {
                if(board[r][c] == chess
                        && board[r + 1][c - 1] == chess
                        && board[r + 2][c - 2] == chess
                        && board[r + 3][c - 3] == chess
                        && board[r + 4][c - 4] == chess){
                    return chess == 1?user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }
        return 0;
    }

    public int getWhiteUser() {
        return whiteUser;
    }

    public void setWhiteUser(int whiteUser) {
        this.whiteUser = whiteUser;
    }

    public String getRoomId() {
        return roomId;
    }

    public void setRoomId(String roomId) {
        this.roomId = roomId;
    }

    public UserInfo getUser1() {
        return user1;
    }

    public void setUser1(UserInfo user1) {
        this.user1 = user1;
    }

    public UserInfo getUser2() {
        return user2;
    }

    public void setUser2(UserInfo user2) {
        this.user2 = user2;
    }

    //在创建房间时自动分配这里的
    public Room(){
        roomId = UUID.randomUUID().toString();
        onlineUser = JavaGobangApplication.context.getBean(OnlineUser.class);
        roomManager = JavaGobangApplication.context.getBean(RoomManager.class);
        userInfoMapper = JavaGobangApplication.context.getBean(UserInfoMapper.class);
    }
}
